package net.trombonium.steroid;

import java.net.*;
import java.util.ArrayList;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.IBinder;
import android.util.*;

import java.io.*;

import org.apache.http.client.methods.*;
import org.apache.http.client.*;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.*;
import org.apache.http.*;

public class WAInterface extends Service {
	
	private static final String URL_BASE = "http://steroid.trombonium.net";
	private static final String TAG = "WAInterface";
	public static final String TODO = "net.trombonium.steroid.todo";
	public static final String SURVEY_ID = "net.trombonium.steroid.todo.surveyid";
	public static final int DO_NOTHING = 0;
	public static final int GET_SURVEYS = 1;
	public static final int POST_RESULTS = 2;
	public static final int CRONJOBS = 3;

	public WAInterface(){
		
	}
	
	public void onStart(Intent intent, int startId){
		super.onStart(intent, startId);
		int toDo = intent.getIntExtra(TODO, DO_NOTHING);
		switch(toDo){
		case GET_SURVEYS:
			Log.i(TAG, "Get Surveys Alarm went off");
			getSurveys(this);
			break;
		case POST_RESULTS:
			int surveyId;
			if((surveyId = intent.getIntExtra(SURVEY_ID, -1)) != -1)
				postResults(this, surveyId);
			break;
		case DO_NOTHING: default:
			//um...do nothing
		}
	}
		
	public void getSurveys(Context ctx){
		try{
			int myId = 1; //should get from db
			String url = URL_BASE + "/mobile/get_survey/" + String.valueOf(myId);
			URL surveyZip = new URL(url);
			String zipFile = saveBinaryFile(surveyZip, "/sdcard/steroid/");
			Log.i(TAG, "zip dl'd");
			
			if(zipFile != null){
				ArrayList<String> sqlFiles = SteroidZip.unzipAll(zipFile, "/sdcard/steroid/");
				//Log.i(TAG, "zip uz'd");
				
				DBHelper dbHelper = new DBHelper(ctx);
				dbHelper.runSQLFiles(sqlFiles);
				//Log.i(TAG, "zip sql'd");
				
				considerRunningSurveys(sqlFiles);
				//Log.i(TAG, "survey run");
			}
		}
		catch(Exception e){
			Log.e(TAG, "Unable to download survey. "+e.getMessage());
			StringWriter stack = new StringWriter();
			e.printStackTrace(new PrintWriter(stack));
			Log.e(TAG, stack.toString());
		}
	}
	
	private void considerRunningSurveys(ArrayList<String> sqlFiles){
		DBHelper dbHelper = new DBHelper(this);
		for(int i=0; i<sqlFiles.size(); ++i){
			String strSurveyId = sqlFiles.get(i);
			strSurveyId = strSurveyId.substring(16, strSurveyId.indexOf("/sql")); //16 is length of "/sdcard/steroid/"
			int surveyId = Integer.parseInt(strSurveyId);
			if(dbHelper.runImmed(surveyId)){
				Notify.setSurveyNotification(this, surveyId);
			}
			dbHelper.parseCronjobs("survey_id="+String.valueOf(surveyId));
		}
	}
	
	public void postResults(Context ctx, int surveyId){
		try{
			DBHelper dbHelper = new DBHelper(ctx);
			String dir = "/sdcard/steroid/"+String.valueOf(surveyId);//+"/results";
			(new File(dir+"/results")).mkdir();
			BufferedWriter sqlOut = new BufferedWriter(new FileWriter(dir+"/results/sql"));
			sqlOut.write(dbHelper.getResultsSQL(surveyId));
			sqlOut.close();
			
			String zipfile = dir+"/"+String.valueOf(surveyId)+".zip";
			SteroidZip.ZipMe(dir+"/results", zipfile);
			
			String userId = String.valueOf(dbHelper.getUserId());
			upload(zipfile, URL_BASE + "/mobile/post_results/"+userId);
			
			dbHelper.clearResults(surveyId);
		}
		catch(Exception e){
			Log.e(TAG, "Unable to upload results. " + e.getMessage());
			e.printStackTrace();
		}
	}
	
	//this method borrowed from http://www.java2s.com/Code/Java/Network-Protocol/Savebinaryfilefromweb.htm
	private static String saveBinaryFile(URL u, String outDirectory) {
		int bufferLength = 128;
		try {
			URLConnection uc = u.openConnection();
			String ct = uc.getContentType();
			int contentLength = uc.getContentLength();
			if (ct.startsWith("text/") || contentLength == -1) {
				//System.err.println("This is not a binary file.");
				return null;
			}

			InputStream stream = uc.getInputStream();
			byte[] buffer = new byte[contentLength];
			int bytesread = 0;
			int offset = 0;
			while (bytesread >= 0) {
				bytesread = stream.read(buffer, offset, Math.min(bufferLength, buffer.length-offset));
				if (bytesread == -1)
					break;
				offset += bytesread;
			}
			if (offset != contentLength) {
				System.err.println("Error: Only read " + offset + " bytes");
				System.err.println("Expected " + contentLength + " bytes");
			}

			String theFile = u.getFile();
			theFile = outDirectory + theFile.substring(theFile.lastIndexOf('/') + 1);
			FileOutputStream fout = new FileOutputStream(theFile);
			fout.write(buffer);
			return theFile;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	//code borrowed from http://getablogger.blogspot.com/2008/01/android-how-to-post-file-to-php-server.html
	//...and then was severely modified for style
	public void upload(String filename, String url){
		String lineEnd = "\r\n";
		String twoHyphens = "--";
		String boundary = "*****";
		try
		{
			FileInputStream fileInputStream = new FileInputStream(filename);
			//------------------ CLIENT REQUEST
			// Open a HTTP connection to the URL

			HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setUseCaches(false);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("Content-Type", "multipart/form-data;boundary="+boundary);

			DataOutputStream dos = new DataOutputStream( conn.getOutputStream() );

			dos.writeBytes(twoHyphens + boundary + lineEnd);
			dos.writeBytes("Content-Disposition: form-data; name=\"resultsfile\";filename=\"" + filename +"\"" + lineEnd);
			dos.writeBytes(lineEnd);

			// create a buffer of maximum size
			int bytesAvailable = fileInputStream.available();
			int maxBufferSize = 1024;
			int bufferSize = Math.min(bytesAvailable, maxBufferSize);
			byte[] buffer = new byte[bufferSize];

			// read file and write it into form...
			int bytesRead = fileInputStream.read(buffer, 0, bufferSize);

			while (bytesRead > 0)
			{
				dos.write(buffer, 0, bufferSize);
				bytesAvailable = fileInputStream.available();
				bufferSize = Math.min(bytesAvailable, maxBufferSize);
				bytesRead = fileInputStream.read(buffer, 0, bufferSize);
			}

			// send multipart form data necesssary after file data...
			dos.writeBytes(lineEnd);
			dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

			// close streams
			fileInputStream.close();
			dos.flush();

			InputStream is = conn.getInputStream();
			// retrieve the response from server
			int ch;
			StringBuffer b =new StringBuffer();
			while( ( ch = is.read() ) != -1 ){
				b.append( (char)ch );
			}
			String s=b.toString();
			//Log.i("Response",s);
			dos.close();
		}
		catch (MalformedURLException ex)
		{
			Log.e(TAG, "error: " + ex.getMessage(), ex);
		}

		catch (IOException ioe)
		{
			Log.e(TAG, "error: " + ioe.getMessage(), ioe);
		}
	}

	//junk methods
	public void onDestroy(){
		
	}
	
	public IBinder onBind(Intent intent){
		return null;
	}
}

